package com.utils.exception;

import com.alibaba.fastjson2.JSON;
import com.fasterxml.jackson.core.type.TypeReference;
import feign.FeignException;
import io.swagger.v3.oas.annotations.parameters.RequestBody;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;

import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Optional;

@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {
    /**
     * 处理所有参数校验异常
     */
    // 处理 ConstraintViolationException 异常
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(value = HttpStatus.BAD_REQUEST)
    @RequestBody()
    public ResponseEntity<String> handleValidationError(MethodArgumentNotValidException e) {
        List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();
        StringBuilder errorMessage = new StringBuilder();
        for (FieldError fieldError : fieldErrors) {
            errorMessage.append(fieldError.getDefaultMessage()).append("。");
        }
        log.error(String.valueOf(errorMessage));
        return new ResponseEntity<>(errorMessage.toString() + e,HttpStatus.BAD_REQUEST);
    }

    @ExceptionHandler(BusinessException.class)
    @ResponseStatus(value = HttpStatus.BAD_REQUEST)
    @RequestBody()
    public ExceptionReturn handleRuntimeException(BusinessException e) {
        log.error(e.getMessage(),e);
        return new ExceptionReturn(500,e.getCode(),e.getMessage());
    }

    @ExceptionHandler(ArithmeticException.class)
    @ResponseStatus(value = HttpStatus.BAD_REQUEST)
    @RequestBody()
    public ResponseEntity<String> arithmeticException(RuntimeException e) {
        log.error(e.getMessage(),e);
        return new ResponseEntity<>(e.getMessage() ,HttpStatus.BAD_REQUEST);
    }

    @ExceptionHandler(NumberFormatException.class)
    @ResponseStatus(value = HttpStatus.BAD_REQUEST)
    @RequestBody()
    public ResponseEntity<String> arithmeticException(NumberFormatException e) {
        log.error(e.getMessage(),e);
        return new ResponseEntity<>(e.getMessage() ,HttpStatus.BAD_REQUEST);
    }
    @ExceptionHandler(RuntimeException.class)
    @ResponseStatus(value = HttpStatus.BAD_REQUEST)
    @RequestBody()
    public ResponseEntity<String> RuntimeException(RuntimeException e) {
        log.error(e.getMessage(),e);
        return new ResponseEntity<>(e.getMessage() ,HttpStatus.BAD_REQUEST);
    }

    @ExceptionHandler( FeignException.class)
    @ResponseStatus(value = HttpStatus.BAD_REQUEST)
    @RequestBody()
    public ExceptionReturn RuntimeException(FeignException exception) {
        log.error("[Feign - Exception] - 捕获到Feign异常!", exception);
        /*
         * 由于上游服务也同样使用了统一数据处理，不管正常还是异常，响应
         * 的都是ResultMessage 。所以这里的responseBody()其实就是
         * ResultMessage 的json 字符串 。
         */
        Optional<ByteBuffer> byteBuffer = exception.responseBody();
        //判断是否有值
        if (byteBuffer.isPresent()) {
            String json = StandardCharsets.UTF_8.decode(byteBuffer.get()).toString();
            if (json.contains("code")){
                //json转实体类
                return JSON.parseObject(json, new TypeReference<ExceptionReturn>() {}.getType());
            }
        }
        //Feign异常响应结果
        return new ExceptionReturn(exception.status() , 500 , exception.getMessage() );
    }
}
